﻿using System;
using System.Collections.Generic;

using Microsoft.Xna.Framework;




namespace FXnaEngine.Interfaces
{
    /// <summary>
    /// All camera messages will be handled by the camera interface. It will allow
    /// anyone in the code that has access to this interface to request camera information.
    /// </summary>
    public class CameraInterface : QSInterface
    {
        /// <summary>
        /// This is the current render camera for the game.
        /// </summary>
        /// <remarks>
        /// Upon creating split-screen support we will need multiple render cameras. We'd need at
        /// least one camera per viewport.
        /// </remarks>
        public Entity RenderCamera
        {
            get { return renderCamera; }
        }
        private Entity renderCamera;

        /// <summary>
        /// Create a <see cref="CameraInterface"/>.
        /// </summary>
        public CameraInterface(FGame game)
            : base(game, InterfaceType.Camera)
        {
            this.game.GameMessage += this.Game_GameMessage;
        }

        public override void Shutdown()
        {
            renderCamera = null;
        }

        /// <summary>
        /// Sets the camera for which rendering will occur.
        /// </summary>
        /// <param name="inCamera">Desired camera to render from</param>        
        private void SetRenderCamera(Entity inCamera)
        {
            this.renderCamera = inCamera;
        }

        /// <summary>
        /// Message listener for messages that are not directed at any particular Entity or Interface.
        /// </summary>
        /// <param name="message">Incoming message</param>
        /// <exception cref="ArgumentException">Thrown if a <see cref="MessageType"/> is not handled properly."/></exception>
        protected virtual void Game_GameMessage(IMessage message)
        {
            ExecuteMessage(message);
        }

        /// <summary>
        /// Message handler for all incoming messages.
        /// </summary>
        /// <param name="message">Incoming message</param>
        /// <remarks>If a message is sent to the interface and not handled by
        /// the interface then it will be forwarded to the current render camera for
        /// handling.</remarks>
        /// <exception cref="ArgumentException">Thrown if a <see cref="MessageType"/> is not handled properly."/></exception>
        public override bool ExecuteMessage(IMessage message)
        {
            switch (message.Type)
            {
                case MessageType.CameraSetRender:
                    {
                        MsgSetRenderEntity camMsg = message as MsgSetRenderEntity;
                        message.TypeCheck(camMsg);

                        SetRenderCamera(camMsg.Entity);
                    }
                    return true;
                case MessageType.CameraGetRenderEntityID:
                    {
                        MsgGetRenderEntity camMsg = message as MsgGetRenderEntity;
                        message.TypeCheck(camMsg);

                        if (null != renderCamera)
                        {
                            camMsg.EntityID = renderCamera.UniqueID;
                        }
                    }
                    return true;
                case MessageType.GraphicsSettingsChanged:
                    {
                        // If we have a render camera, let them know about the change to graphics settings.
                        if (null != renderCamera)
                        {
                            MsgGraphicsSettingsChanged msgChange = ObjectPool.Aquire<MsgGraphicsSettingsChanged>();
                            msgChange.UniqueTarget = renderCamera.UniqueID;
                            this.game.SendMessage(msgChange);
                        }
                    }
                    return true;
                default:
                    return false;
            }
        }
    }
}
